<?php
/**
 * 常用函数库
 * @author wuwenbin <wenbin.wu@foxmail.com>
 * @license http://opensource.org/licenses/MIT The MIT License
 */

// 递归去除\,'转义
function stripslashes_deep($data) {
    if(is_array($data)) return array_map(__FUNCTION__, $data);
    else return stripslashes($data);
}

// 对字符(',\)转义
function addslashes_deep($data) {
    if(is_array($data)) return array_map(__FUNCTION__, $data);
    else return addslashes($data);
}

// 解析ini字符串
function parse_ini($str, $process_sections = false) {
    $rows = preg_split('/\r|\n|\r\n/', $str);
    $sections = array(array());
    $section_in = 0;
    foreach($rows as $v) {
        // 注释
        if(preg_match('/^\s*;/', $v)) {
            continue;
        }
        // 节
        if(preg_match('/^\s*\[([^\]]*)\]/U', $v, $r)) {
            if($process_sections) {
                $section_in = $r[1];
                if(!isset($sections[$section_in])) $sections[$section_in] = array();
            }
            continue;
        }
        // 键 = 值
        if(preg_match('/^([^=]*)=(.*)$/', $v, $r)) {
            $key = trim($r[1]);
            $value = trim($r[2]);
            $sections[$section_in][$key] = $value;
        }
    }
    if($process_sections) {
        if(empty($sections[0])) unset($sections[0]);
        return $sections;
    } else {
        return $sections[0];
    }
}

// 数据库查询日志
function mysql_query_log($info) {
    file_log::save("mysql", print_r($info, 1), file_log::mode_default);
}

// 构造插入语句
function build_insert_sql($table, $data) {
    if(!is_array($data) || empty($data)) return "";
    $sql = "insert into $table";
    $fields = "";
    $values = "";
    foreach($data as $k => $v) {
        $fields .= "`$k`,";
        $values .= "'$v',";
    }
    $fields = trim($fields, ",");
    $values = trim($values, ",");
    $sql .= "($fields) values($values)";
    return $sql;
}

// 构造替换语句
function build_replace_sql($table, $data) {
    if(!is_array($data) || empty($data)) return "";
    $sql = "replace into $table";
    $fields = "";
    $values = "";
    foreach($data as $k => $v) {
        $fields .= "`$k`,";
        $values .= "'$v',";
    }
    $fields = trim($fields, ",");
    $values = trim($values, ",");
    $sql .= "($fields) values($values)";
    return $sql;
}

// 构造更新语句
function build_update_sql($table, $data, $where = "") {
    if(!is_array($data) || empty($data)) return "";
    $sql = "update $table set ";
    foreach($data as $k => $v) {
        $sql .= "`$k` = '$v',";
    }
    $sql = trim($sql, ",").($where ? " where $where" : "");
    return $sql;
}

// 获取记录集列集合
function get_col($fields, array $data) {
    $cols = array();
    if(is_array($fields)) {
        $is_one = false;
    } else {
        $is_one = true;
        $fields = array((string)$fields);
    }

    foreach($fields as $v) $cols[$v] = array();
    foreach($data as $k => $v) {
        foreach($fields as $v1) {
            if(isset($v[$v1])) $cols[$v1][$k] = $v[$v1];
        }
    }

    return $is_one ? $cols[$fields[0]] : $cols;
}

// 判断是否为POST请求
function is_post() {
    $method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : "";
    return strtoupper($method) == "POST" ? true : false;
}

// 判断是否为GET请求
function is_get() {
    $method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : "";
    return strtoupper($method) == "GET" ? true : false;
}

// 判断是否为AJAX请求
function is_ajax() {
    if(isset($_SERVER['HTTP_X_REQUESTED_WITH'])) {
        if(strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') return true;
    }
    return false;
}

// 判断是否为HTTPS请求
function is_https() {
    $https = isset($_SERVER["HTTPS"]) ? $_SERVER["HTTPS"] : "";
    return ($https == "on") ? true : false;
}

// 获取GET请求数据
function G($key, $default = null) {
    return isset($_GET[$key]) ? $_GET[$key] : $default;
}

// 获取POST请求数据
function P($key, $default = null) {
    return isset($_POST[$key]) ? $_POST[$key] : $default;
}

// 获取REQUEST(GET/POST)数据
function R($key, $default = null) {
    return isset($_REQUEST[$key]) ? $_REQUEST[$key] : $default;
}

// 构造数字验证码(修改自thinkphp)
function build_verify_image($width = 48, $height = 22) {
    $verify_code = "";
    $chars = "1234567890";
    $length = 4;
    $im = imagecreate($width, $height);
    $r = Array(225, 255, 255, 223);
    $g = Array(225, 236, 237, 255);
    $b = Array(225, 236, 166, 125);
    $key = mt_rand(0, 3);
    $back_color = imagecolorallocate($im, $r[$key], $g[$key], $b[$key]);
    $border_color = imagecolorallocate($im, 100, 100, 100);
    $string_color = imagecolorallocate($im, mt_rand(0, 200), mt_rand(0, 120), mt_rand(0, 120));
    imagefilledrectangle($im, 0, 0, $width - 1, $height - 1, $back_color);
    imagerectangle($im, 0, 0, $width - 1, $height - 1, $border_color);
    // 干扰
    for ($i = 0; $i < 10; $i++) {
        imagearc($im, mt_rand(-10, $width), mt_rand(-10, $height), mt_rand(30, 300), mt_rand(20, 200), 55, 44, $string_color);
    }
    for ($i = 0; $i < 25; $i++) {
        imagesetpixel($im, mt_rand(0, $width), mt_rand(0, $height), $string_color);
    }
    for ($i = 0; $i < $length; $i++) {
        $char = substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        imagestring($im, 5, $i * 10 + 5, mt_rand(1, 8), $char, $string_color);
        $verify_code .= $char;
    }
    header("content-type: image/png");
    imagepng($im);
    imagedestroy($im);
    return $verify_code;
}

//字符串截取(模式:0:英文+1中文+2;1:英文+1,中文+1)
function str_cut($str, $length, $ext = '', $mode = 0) {
    $len = 0;
    $output = '';
    // preg_match_all("/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/", $str, $match);
    preg_match_all("/./us", $str, $match);

    // 模式0:英文+1;中文+2;
    if($mode == 0) {
        foreach($match[0] as $v) {
            if(strlen($v) > 1) $len += 2;
            else $len += 1;
            $output .= $v;
            if($len >= $length) break;
        }
    }
    // 模式1:英文+1;中文+1;
    elseif($mode == 1) {
        $output = join("",array_slice($match[0], 0, $length));
    } else {
        return '';
    }

    if(strlen($output) < strlen($str)) $output .= $ext;
    return $output;
}

// 获取字符串长度(0:系统默认模式;1:中文+2,英文+1;2:中文+1,英文+1)
function get_str_len($str, $model = 0) {
    if($model == 0) {
        return strlen($str);
    }
    if($model == 1) {
        $count = 0;
        preg_match_all("/./us", $str, $match);
        foreach($match[0] as $v) {
            if(strlen($v) == 1) {
                $count += 1;
            } else {
                $count += 2;
            }
        }
        return $count;
    }
    if($model == 2) {
        preg_match_all("/./us", $str, $match);
        return count($match[0]);
    }
}

// 获取当前网址
function get_cur_url() {
    return "http".(is_https() ? "s" : "")."://".$_SERVER["HTTP_HOST"].$_SERVER["REQUEST_URI"];
}

// 获取来路网址
function get_referer_url() {
    return isset($_SERVER["HTTP_REFERER"]) ? $_SERVER["HTTP_REFERER"] : "";
}

// 获取客户端IP(修改自thinkphp)
function get_client_ip() {
    static $ip = NULL;
    if ($ip !== NULL) return $ip;
    if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
        $pos =  array_search('unknown',$arr);
        if(false !== $pos) unset($arr[$pos]);
        $ip   =  trim($arr[0]);
    }elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
        $ip = $_SERVER['HTTP_CLIENT_IP'];
    }elseif (isset($_SERVER['REMOTE_ADDR'])) {
        $ip = $_SERVER['REMOTE_ADDR'];
    }
    // IP地址合法验证
    $ip = (false !== ip2long($ip)) ? $ip : '';
    return $ip;
}

// htmlspecialchars别名
function H($str) {
    return htmlspecialchars($str);
}

// COOKIE读写
function cookie($key, $value = "", $expire = 0, $domain = "") {
    if(func_num_args() == 1){
        if(isset($_COOKIE[$key])) return $_COOKIE[$key];
        return null;
    } else {
        if($expire != 0) $expire = time()+$expire;
        return setcookie($key, $value, $expire, "/", $domain);
    }
}

// SESSION读写
function session($key, $value = "") {
    isset($_SESSION) || session_start();
    if(func_num_args() == 1) {
        return isset($_SESSION[$key]) ? $_SESSION[$key] : null;
    } else {
        $_SESSION[$key] = $value;
    }
}

// 全局错误
function error($err = null) {
    static $_err = "";
    if(is_null($err)) {
        return $_err;
    } else {
        $_err = $err;
    }
}

// 返回json应答数据
function return_json($flag, $info = '', $data = '') {
    $return["flag"] = (int)$flag;
    $return["info"] = (string)$info;
    $return["data"] = $data;
    echo json_encode($return);
    exit;
}

// 构造数据签名
function build_signature(array $params, $key) {
    $tmp = array();
    foreach($params as $k => $v) $tmp[] = $k.$v;
    sort($tmp);
    return strtoupper(md5($key.implode("", $tmp).$key));
}

// 生成随即数
function get_rand_str($len, $ext_chars = "") {
    $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".$ext_chars;
    $output = "";
    for($i = 0; $i < $len; $i++) {
        $key = rand(0, 1000) % strlen($chars);
        $output .= $chars[$key];
    }
    return $output;
}

// 获取数组键值
function array_get($arr, $key, $default = null) {
    return isset($arr[$key]) ? $arr[$key] : $default;
}

// JS信息提示
function alert($msg, $url) {
    $msg = json_encode($msg);
    $url = json_encode($url);
    echo "<script type=\"text/javascript\">alert({$msg}); location.href = {$url};</script>";
    exit;
}

// 扩展退出提示
function _exit($msg) {
    @header("content-type: text/html; charset=utf-8");
    exit("$msg");
}

// 分页函数
function page_html($url, $page, $count, $each) {
    $page = max((int)$page, 1);
    $each = max((int)$each, 1);
    $count = (int)$count;
    if($count < 1) return "<span>共0条记录</span> ";
    $total_page = ceil($count / $each);
    $html = "<strong>$page</strong> ";
    $len = 6;
    $l = $r = 1;
    while(1) {
        if($page - $l > 0) {
            $_page = $page - $l;
            $_url = str_replace("[p]", $_page, $url);
            $html = '<a href="'.$_url.'">'.$_page.'</a> '.$html;
            $l++;
            $len--;
        }
        if($len == 0) break;
        if($page + $r < $total_page + 1) {
            $_page = $page + $r;
            $_url = str_replace("[p]", $_page, $url);
            $html .= '<a href="'.$_url.'">'.$_page.'</a> ';
            $r++;
            $len--;
        }
        if($len == 0) break;
        if($page - $l <= 0 && $page + $r > $total_page) break;
    }

    if($page - 1 > 0) {
        $_page = $page - 1;
        $_url = str_replace("[p]", $_page, $url);
        $html = '<a href="'.$_url.'">上页</a> '.$html;
    } else {
        $html = '<a href="javascript:;">上页</a> '.$html;
    }

    if($page + 1 < $total_page + 1) {
        $_page = $page + 1;
        $_url = str_replace("[p]", $_page, $url);
        $html .= '<a href="'.$_url.'">下页</a> ';
    } else {
        $html .= '<a href="javascript:;">下页</a> ';
    }

    if($page > 1) {
        $_page = 1;
        $_url = str_replace("[p]", $_page, $url);
        $html = '<a href="'.$_url.'">首页</a> '.$html;
    } else {
        $html = '<a href="javascript:;">首页</a> '.$html;
    }

    if($page < $total_page) {
        $_page = $total_page;
        $_url = str_replace("[p]", $_page, $url);
        $html .= '<a href="'.$_url.'">末页</a> ';
    } else {
        $html .= '<a href="javascript:;">末页</a> ';
    }

    $html = "<span>共{$total_page}页/{$count}条记录</span> ".$html;
    return $html;
}

// 获取用于分页的url
function get_page_url() {
    $cur_url = "http".(is_https() ? "s" : "")."://".$_SERVER["HTTP_HOST"].$_SERVER["REQUEST_URI"];
    if(preg_match("/page=(\d+)/", $cur_url)) {
        return preg_replace("/page=(\d+)/", "page=[p]", $cur_url);
    } else {
        return $cur_url.(strpos($cur_url, "?") ? "&" : "?")."page=[p]";
    }
}

// URL重定向
function redirect($url) {
    @header('location:'.$url);
    exit;
}

// 清空目录
function clean_dir($path, &$list = null) {
    if(!is_dir($path)) return null;
    $handle = @opendir($path);
    while($file = @readdir($handle)) {
        if($file == '.' || $file == '..') continue;
        if(is_dir($path.'/'.$file)) {
            clean_dir($path.'/'.$file, $list);
            if(!@rmdir($path.'/'.$file)) {
                @chmod($path.'/'.$file, 0777);
                @rmdir($path.'/'.$file);
            }
            if(!file_exists($path.'/'.$file)) $list[] = $path.'/'.$file;
        } else {
            if(!@unlink($path.'/'.$file)) {
                @chmod($path.'/'.$file, 0777);
                @unlink($path.'/'.$file);
            }
            if(!file_exists($path.'/'.$file)) $list[] = $path.'/'.$file;
        }
    }
}

// 构造唯一ID
function uuid($prefix = "") {
    $time = md5(microtime());
    $rand1 = md5(substr($time, rand(0,10), rand(22,32)));
    $rand2 = md5(substr($rand1, rand(0,10), rand(22,32)));
    $id = strtolower(md5($prefix.$ip.$time.$rand1.$rand2));
    return $id;
}

// 数组递归覆盖
function array_merge_deep(array &$arr1, array $arr2) {
    foreach($arr2 as $k => $v) {
        if(!isset($arr1[$k])) $arr1[$k] = $v;
        else {
            if(!is_array($arr1[$k]) || !is_array($v)) $arr1[$k] = $v;
            else array_merge_deep($arr1[$k], $v);
        }
    }
}

// 检查邮件格式是否合法
function is_valid_email($email) {
    return (bool)preg_match("/[_a-zA-Z\d\-\.]+@[_a-zA-Z\d\-]+(\.[_a-zA-Z\d\-]+)+$/i", $email);
}

// 检查域名格式是否合法
function is_valid_domain($domain) {
    return (bool)preg_match("/^([a-z0-9\-]+\.)+([a-z]{2,})$/i", $domain);
}

// 检查手机号码是否合法(11位大陆号码)
function is_valid_mobile_number($mobile_no) {
    return (bool)preg_match("/^(13|14|15|17|18)\d{9}$/", $mobile_no);
}

// 字符串加密/解密(修改自discuz)
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {

    $ckey_length = 4;

    $key = md5($key);
    $keya = md5(substr($key, 0, 16));
    $keyb = md5(substr($key, 16, 16));
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';

    $cryptkey = $keya.md5($keya.$keyc);
    $key_length = strlen($cryptkey);

    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
    $string_length = strlen($string);

    $result = '';
    $box = range(0, 255);

    $rndkey = array();
    for($i = 0; $i <= 255; $i++) {
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
    }

    for($j = $i = 0; $i < 256; $i++) {
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
        $tmp = $box[$i];
        $box[$i] = $box[$j];
        $box[$j] = $tmp;
    }

    for($a = $j = $i = 0; $i < $string_length; $i++) {
        $a = ($a + 1) % 256;
        $j = ($j + $box[$a]) % 256;
        $tmp = $box[$a];
        $box[$a] = $box[$j];
        $box[$j] = $tmp;
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
    }

    if($operation == 'DECODE') {
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
            return substr($result, 26);
        } else {
            return '';
        }
    } else {
        return $keyc.str_replace('=', '', base64_encode($result));
    }

}

// 控制台打印表格
function print_table(array $list, array $title = array(), $return = false) {
    $res = "";
    if(empty($list)) {
        if($return) return $res;
        else exit($res);
    }

    foreach($list as $k => $v) {
        if(is_array($v)) {
            $i = 0;
            foreach($v as $_k => $_v) {
                $_v = (string)$_v;
                $list[$k][$_k] = $_v;
                if(!isset($widths[$i])) $widths[$i] = 0;
                $widths[$i] = max($widths[$i], mb_strwidth($_v, "utf-8"));
                $i++;
            }
        } else {
            $v = (string)$v;
            $list[$k] = array($v);
            if(!isset($widths[0])) $widths[0] = 0;
            $widths[0] = max($widths[0], mb_strwidth($v, "utf-8"));
        }
    }

    $i = 0;
    foreach($title as $k => $v) {
        $v = (string)$v;
        $title[$k] = $v;
        if(!isset($widths[$i])) $widths[$i] = 0;
        $widths[$i] = max($widths[$i], mb_strwidth($v, "utf-8"));
        $i++;
    }

    if(empty($widths)) {
        if($return) return $res;
        else exit($res);
    }

    $line = "";
    for($i = 0; $i < count($widths); $i++) {
        if($i == 0) {
            $line .= "+";
        }
        $line .= "-".str_repeat("-", $widths[$i])."-+";
    }

    if($return) {
        $res .= "$line\n";
    } else {
        echo "$line\n";
    }

    if(!empty($title)) {
        $line = "";
        $i = 0;
        foreach($title as $v) {
            if($i == 0) {
                $line .= "|";
            }
            $line .= " ".$v.str_repeat(" ", max(0, $widths[$i] - mb_strwidth($v, "utf-8")))." |";
            $i++;
        }

        for(; $i < count($widths); $i++) {
            if($i == 0) {
                $line .= "|";
            }
            $line .= " ".str_repeat(" ", $widths[$i])." |";
        }

        if($return) {
            $res .= "$line\n";
        } else {
            echo "$line\n";
        }

        $line = "";
        for($i = 0; $i < count($widths); $i++) {
            if($i == 0) {
                $line .= "+";
            }
            $line .= "-".str_repeat("-", $widths[$i])."-+";
        }

        if($return) {
            $res .= "$line\n";
        } else {
            echo "$line\n";
        }
    }

    foreach($list as $v) {
        $line = "";
        $i = 0;
        foreach($v as $_v) {
            if($i == 0) {
                $line .= "|";
            }
            $line .= " ".$_v.str_repeat(" ", max(0, $widths[$i] - mb_strwidth($_v, "utf-8")))." |";
            $i++;
        }

        for(; $i < count($widths); $i++) {
            if($i == 0) {
                $line .= "|";
            }
            $line .= " ".str_repeat(" ", $widths[$i])." |";
        }

        if($return) {
            $res .= "$line\n";
        } else {
            echo "$line\n";
        }
    }

    $line = "";
    for($i = 0; $i < count($widths); $i++) {
        if($i == 0) {
            $line .= "+";
        }
        $line .= "-".str_repeat("-", $widths[$i])."-+";
    }

    if($return) {
        $res .= "$line\n";
    } else {
        echo "$line\n";
    }

    if($return) {
        return $res;
    }
}

// XML节点查找
function get_xml_node($xml, $path, $multi = false) {
    $list = array();
    $_list = array();

    if($xml instanceof DOMNode) {
        $list[] = $xml;
    }
    elseif(is_array($xml)) {
        foreach($xml as $v) {
            if($xml instanceof DOMNode) {
                $list[] = $xml;
            }
        }
    }
    elseif(is_string($xml)) {
        $doc = new DOMDocument("1.0", "utf-8");
        $res = $doc->loadXML(trim($xml));
        if($res) {
            $list[] = $doc;
        }
    }

    $tmp = explode("/", $path);
    foreach($tmp as $node_name) {
        if(trim($node_name) == "") {
            continue;
        }
        foreach($list as $v) {
            foreach($v->childNodes as $_v) {
                if($_v->nodeName == $node_name) {
                    $_list[] = $_v;
                }
            }
        }
        $list = $_list;
        $_list = array();
    }

    if(empty($list)) {
        return null;
    }

    if($multi) {
        return $list;
    } else {
        return $list[0];
    }
}

// 导出数据为csv格式
function export_csv($filename, array $title, array $data, $charset="UTF-8") {
    header("Cache-Control: public");
    header("Pragma: public");
    header("Content-Type: application/vnd.ms-excel");
    header("Content-Disposition: attachment; filename=$filename.csv");
    header("Content-Type: application/octet-stream");
    header("Content-Type: application/download");
    header("Content-Type: application/force-download");

    $str = "";
    foreach($title as $v) {
        $v = str_replace(array("\\", "\""), array("\\\\", "\\\""), (string)$v);
        $str .= "\"".iconv($charset, "UTF-8", $v)."\",";
    }
    $str .= "\n";

    foreach($data as $_v) {
        foreach((array)$_v as $v) {
            $v = str_replace(array("\\", "\""), array("\\\\", "\\\""), (string)$v);
            $str .= "\"".iconv($charset, "UTF-8", $v)."\",";
        }
        $str .="\n";
    }

    echo $str;
}

